package com.example.emailcraft.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.emailcraft.entity.Users;
import com.example.emailcraft.entity.common.Result;
import com.example.emailcraft.entity.request.LoginRequest;
import com.example.emailcraft.entity.request.RegisterRequest;
import com.example.emailcraft.entity.response.IsLoginResponse;
import com.example.emailcraft.entity.response.LoginResponse;
import com.example.emailcraft.handler.GlobalExceptionHandler;
import com.example.emailcraft.interceptor.CurrentUserHolder;
import com.example.emailcraft.mapper.UsersMapper;
import com.example.emailcraft.service.IRolesService;
import com.example.emailcraft.service.IUsersService;
import com.example.emailcraft.utils.IpUtils;
import com.example.emailcraft.utils.JwtUtil;
import com.example.emailcraft.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author scj
 * @since 2025-01-21
 */
@Service
@Slf4j
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements IUsersService {

    @Autowired
    private UserUtils userUtils;

    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private IRolesService rolesService;

    @Autowired
    private IpUtils ipUtils;

    @Override
    public ResponseEntity<Result<Object>> login(LoginRequest request, HttpServletResponse response) {
        try {

            // 2. 执行用户认证
            Users user = userUtils.authenticate(
                    request.getUsername(),
                    request.getPassword()
            );

            // 3. 获取用户角色
            List<String> roles = usersMapper.getUserRoles(Long.valueOf(user.getId()));
            String rolesString = String.join(",", roles);

            // 4. 生成JWT令牌
            String token = JwtUtil.generateToken(
                    Long.valueOf(user.getId()),
                    user.getUsername(),
                    rolesString
            );

            // 5. 构建响应数据（排除敏感信息）
            LoginResponse responseData = new LoginResponse(
                    token,
                    user.getUsername(),
                    rolesString,
                    JwtUtil.getExpiration()
            );

            // 6. 记录成功日志
            log.info("用户登录成功: {}", user.getUsername());
            // 创建 Cookie
            Cookie tokenCookie = new Cookie("token", token);
            tokenCookie.setPath("/");
            tokenCookie.setMaxAge(86400 * 7); // 7 天
            tokenCookie.setHttpOnly(true);

            // 将 Cookie 添加到响应中
            response.addCookie(tokenCookie);
            return ResponseEntity.ok(
                    new Result<>().setCode(HttpStatus.OK.value()).setMessage("登录成功").setData(responseData)
            );

        } catch (GlobalExceptionHandler.BusinessException e) {
            // 7. 业务异常由全局处理器统一处理
            throw e;
        }
    }

    @Override
    @Transactional
    public ResponseEntity<Result<Object>> register(RegisterRequest request) {
        try {
            // 1. 检查用户名是否已存在
            if (usersMapper.findByUsername(request.getUsername()) != null) {
                throw new GlobalExceptionHandler.BusinessException(GlobalExceptionHandler.ErrorCode.BAD_REQUEST, "用户名已存在");
            }

            // 2. 检查邮箱是否已存在
            if (usersMapper.findByEmail(request.getEmail()) != null) {
                throw new GlobalExceptionHandler.BusinessException(GlobalExceptionHandler.ErrorCode.BAD_REQUEST, "邮箱已存在");
            }
            // 3. 检查密码是否为空
            if (request.getPassword() == null || request.getPassword().isEmpty()) {
                throw new GlobalExceptionHandler.BusinessException(GlobalExceptionHandler.ErrorCode.BAD_REQUEST, "密码不能为空");
            }
            // 3. 对密码进行加密
            String passwordHash = passwordEncoder.encode(request.getPassword());

            // 4. 创建用户对象
            Users user = new Users();
            user.setUsername(request.getUsername());
            user.setEmail(request.getEmail());
            user.setPasswordHash(passwordHash);
            user.setCreatedAt(LocalDateTime.now());
            user.setUpdatedAt(LocalDateTime.now());
            user.setIsLocked(0); // 默认账户未锁定
            user.setFailedAttempts(0); // 默认登录失败次数为0

            // 5. 保存用户到数据库
            usersMapper.insert(user);

            // 6. 为用户分配默认角色（如 USER）
            rolesService.assignDefaultRoleToUser(user.getId());

            // 7. 返回成功响应
            return ResponseEntity.ok(
                    new Result<>().setCode(HttpStatus.OK.value()).setMessage("注册成功").setData(null)
            );

        } catch (GlobalExceptionHandler.BusinessException e) {
            // 8. 业务异常由全局处理器统一处理
            throw e;
        }
    }

    @Override
    public ResponseEntity<Result<Object>> IsLogin(HttpServletRequest request) {
        try {
            //1.获取用户信息
            Integer userId = Math.toIntExact(CurrentUserHolder.getRequired().getUserId());
            Users user = usersMapper.selectById(userId);
            if (user == null) {
                //2.返回用户信息
                IsLoginResponse isLoginResponse = new IsLoginResponse();
                isLoginResponse.setLogin(false);
                isLoginResponse.setUsername(null);
                isLoginResponse.setIp(ipUtils.getClientIpAddress(request));
                return ResponseEntity.ok(
                        new Result<>().setCode(HttpStatus.OK.value()).setMessage("未登录").setData(null)
                );
            }
            //2.返回用户信息
            IsLoginResponse isLoginResponse = new IsLoginResponse();
            isLoginResponse.setLogin(true);
            isLoginResponse.setUsername(user.getUsername());
            isLoginResponse.setIp(ipUtils.getClientIpAddress(request));
            return ResponseEntity.ok(
                    new Result<>().setCode(HttpStatus.OK.value()).setMessage("success").setData(isLoginResponse)
            );

        } catch (GlobalExceptionHandler.BusinessException e) {
            // 8. 业务异常由全局处理器统一处理
            throw e;
        }
    }
}